package com.lidong.lowcode.model.service.impl;

import com.lidong.config.domain.gloabreturn.ResponseInfo;
import com.lidong.lowcode.base.domain.TreeVO;
import com.lidong.lowcode.base.domain.baseconst.TreeConst;
import com.lidong.lowcode.model.service.BaseGroupService;
import com.lidong.lowcode.model.domain.BaseGroup;
import com.lidong.lowcode.model.domain.BaseGroupExample;
import com.lidong.lowcode.model.domain.modelconst.ModelConst;
import com.lidong.lowcode.model.domain.modelconst.ModelHelperConst;
import com.lidong.lowcode.model.mapper.BaseGroupMapper;
import com.lidong.toolkit.utils.ListUtils;
import com.lidong.toolkit.utils.MapUtils;
import com.lidong.toolkit.utils.UuidUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LiDong
 * @version 1.0.0
 * @createTime 7/21/2022 9:02 PM
 */
@Service
public class BaseGroupServiceImpl implements BaseGroupService {

    @Autowired
    private BaseGroupMapper baseGroupMapper;

    /**
     * 根据类型获取分组树
     *
     * @param groupType 分组类型
     * @return ResponseInfo
     */
    @Override
    public ResponseInfo<List<TreeVO>> getBaseGroupTreeByType(String groupType) {
        Assert.notNull(groupType, "分组不能为空！");
        List<BaseGroup> baseGroups = Optional.ofNullable(baseGroupMapper.selectByExample(new BaseGroupExample())).orElse(Collections.emptyList());
        List<BaseGroup> groups = baseGroups.stream().filter(x -> groupType.equalsIgnoreCase(x.getType())).collect(Collectors.toList());
        List<TreeVO> trees = new ArrayList<>();
        List<BaseGroup> rootNodes = groups.stream().filter(x -> TreeConst.ROOT_CODE.equals(x.getParentId())).collect(Collectors.toList());
        for (BaseGroup rootNode : rootNodes) {
            TreeVO treeVO = new TreeVO();
            treeVO.setId(rootNode.getId());
            treeVO.setName(rootNode.getGroupName());
            treeVO.setCode(rootNode.getGroupCode());
            treeVO.setParentId(rootNode.getParentId());
            List<TreeVO> children = new ArrayList<>();
            this.dealChildren(treeVO.getId(), children, groups);
            treeVO.setChildren(children);
            trees.add(treeVO);
        }
        return ResponseInfo.success(trees);
    }

    /**
     * 保存数据源
     *
     * @param paramMap
     * @return ResponseInfo
     */
    @Override
    public ResponseInfo<String> saveBaseGroup(Map<String, String> paramMap) {
        BaseGroup baseGroup = MapUtils.mapToObject(paramMap, BaseGroup.class);
        String id = baseGroup.getId();
        if (ObjectUtils.isEmpty(id)) {
            baseGroup.setType(ModelConst.DATASOURCE_CODE);
            baseGroup.setId(UuidUtils.randomUuid());
            if (ObjectUtils.isEmpty(baseGroup.getParentId())) {
                baseGroup.setParentId(ModelHelperConst.ROOT_ID);
            }
            baseGroupMapper.insertSelective(baseGroup);
            return ResponseInfo.success(ResponseInfo.SUCCESS, "保存成功！");
        } else {
            baseGroupMapper.updateByPrimaryKey(baseGroup);
            return ResponseInfo.success(ResponseInfo.SUCCESS, "修改成功！");
        }
    }

    /**
     * 删除分组
     *
     * @param paramMap paramMap
     * @return ResponseInfo
     */
    @Override
    public ResponseInfo<String> deleteBaseGroup(Map<String, Object> paramMap) {
        String type = (String) paramMap.get(ModelHelperConst.L_TYPE);
        Object object = paramMap.get(ModelHelperConst.L_IDS);
        List<Object> list = ListUtils.getList(object);
        for (Object tmpObject : list) {
            Map<String, Object> tmpMap = new HashMap<>();
            tmpMap.put(ModelHelperConst.L_TYPE, type);
            tmpMap.put("id", tmpObject.toString());
            baseGroupMapper.deleteByTypeAndId(tmpMap);
        }
        return ResponseInfo.success(ResponseInfo.SUCCESS, "删除成功！");
    }

    /**
     * 递归处理树分组
     *
     * @param id       nodeId
     * @param children children
     * @param groups   groups
     */
    private void dealChildren(String id, List<TreeVO> children, List<BaseGroup> groups) {
        List<BaseGroup> childNodes = groups.stream().filter(x -> x.getParentId().equals(id)).collect(Collectors.toList());
        for (BaseGroup childNode : childNodes) {
            TreeVO tempTreeVO = new TreeVO();
            tempTreeVO.setId(childNode.getId());
            tempTreeVO.setName(childNode.getGroupName());
            tempTreeVO.setCode(childNode.getGroupCode());
            tempTreeVO.setParentId(childNode.getParentId());
            List<TreeVO> tempChildren = new ArrayList<>();
            this.dealChildren(tempTreeVO.getId(), tempChildren, groups);
            tempTreeVO.setChildren(tempChildren);
            children.add(tempTreeVO);
        }
    }

}
